package de.ur.iw.wiki.control;

import java.awt.Desktop;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;

import de.ur.iw.interfaces.DataBaseListener;
import de.ur.iw.interfaces.OnSettingsChangedListener;
import de.ur.iw.interfaces.PathListener;
import de.ur.iw.interfaces.WeightInformer;
import de.ur.iw.sql.DataBaseSaver;
import de.ur.iw.sql.WikiSQLHelper;
import de.ur.iw.wiki.PathThread;
import de.ur.iw.wiki.Settings;
import de.ur.iw.wiki.WikiConfig;
import de.ur.iw.wiki.WikiPage;
import de.ur.iw.wiki.WikiPaths;
import de.ur.iw.wiki.gui.WikiGUI;
import de.ur.iw.wiki.weighters.WeightInfo;

public class WikiController implements OnSettingsChangedListener, PathListener,
		DataBaseListener {

	private WikiGUI view;
	private WikiPaths model;
	private static WikiSQLHelper database;

	private WeightInformer informer;

	private int savingProgress = 0;

	public void run() {
		view = new WikiGUI();
		model = new WikiPaths();
		if (view instanceof WeightInformer) {
			informer = (WeightInformer) view;
		}
		view.setOnSettingsChangedListener(this);
		view.display();
	}

	public void start() {
		savingProgress=0;
		for (int i = 0; i < Settings.getDouble(Settings.KEY_MAX_PATHS_VALUE,
				100.0); i++) {
			System.out.println("i=" + i);
			int num = (int) Settings.getDouble(Settings.KEY_LIMITED_STEPS, Settings.DEFAULT_PATH_LENGTH);
			view.log("Path started...");
			PathThread pt = new PathThread(num);
			pt.addPathListener(this);
			pt.start();
		}
	}

	@Override
	public void onSettingsChanged(int key, Object value) {
		switch (key) {
		case Settings.KEY_MAX_PATHS_VALUE:
			Settings.setKey(Settings.KEY_MAX_PATHS_VALUE, (Integer) value);
			break;
		case Settings.KEY_CATEGORIES_WEIGHT:
			Settings.setKey(Settings.KEY_CATEGORIES_WEIGHT, (Double) value);
			break;
		case Settings.KEY_LIMIT_TO_CATEGORIES:
			Settings.setKey(Settings.KEY_CATEGORIES_WEIGHT, 1.0);
			break;
		case Settings.KEY_LIMITED_STEPS:
			Settings.setKey(Settings.KEY_LIMITED_STEPS, (Double) value);
			break;
		case Settings.KEY_RANDOMWALK_START:
			if (informer != null) {
				saveWeightInfo(informer.getWeightInfo());
			}
			start();
			view.setEnabled(false);
			break;
		case Settings.KEY_START_PAGE:
			if (value.toString().trim().length() > 0) {
				Settings.setKey(Settings.KEY_START_PAGE, value.toString());
			}
			break;
		case Settings.KEY_RESULT_LOCATION:
			if (value.toString().trim().length() > 0) {
				Settings.setKey(Settings.KEY_RESULT_LOCATION, value.toString());
			}
			break;
		case Settings.KEY_OPEN_RESULTS:
			openUrl();
			break;
		case Settings.KEY_PREVENT_LOOPS:
			if (value.toString().trim().length() > 0) {
				Settings.setKey(Settings.KEY_PREVENT_LOOPS, (Boolean)value);
			}
			break;
		case Settings.KEY_DEAD_END:
			if (value.toString().trim().length() > 0) {
				Settings.setKey(Settings.KEY_DEAD_END, (Boolean)value);
			}
			break;
		case Settings.KEY_FILES:
			if (value.toString().trim().length() > 0) {
				Settings.setKey(Settings.KEY_FILES, (Boolean)value);
			}
			break;
		default:
			try {
				Settings.setKey(key, (String) value);
			} catch (Exception e) {
				// cast - exception
			}
			break;
		}
	}

	private void saveWeightInfo(WeightInfo info) {
		Settings.setKey(Settings.KEY_WEIGHT_OF_FIRST_LINKS,
				info.getWeightOfFirstLinks());
		Settings.setKey(Settings.KEY_WEIGHT_OF_MIDDLE_LINKS,
				info.getWeightOfMiddleLinks());
		Settings.setKey(Settings.KEY_WEIGHT_OF_LAST_LINKS,
				info.getWeightOfLastLinks());

		Settings.setKey(Settings.KEY_WEIGHT_OF_FIRST_PARAGRAPHS,
				info.getWeightOfFirstParagraphs());
		Settings.setKey(Settings.KEY_WEIGHT_OF_MIDDLE_PARAGRAPHS,
				info.getWeightOfMiddleParagraphs());
		Settings.setKey(Settings.KEY_WEIGHT_OF_LAST_PARAGRAPHS,
				info.getWeightOfLastParagraphs());
	}

	@Override
	public void onPathCompleted(ArrayList<WikiPage> path) {
		model.paths.add(path);
		double percentage = 100 * model.paths.size()
				/ Settings.getDouble(Settings.KEY_MAX_PATHS_VALUE, 100.0);
		view.log(percentage + "%");
		if (percentage >= 100) {
			view.log("inserting paths into database ...");
			saveToDB();
		}
	}

	private void saveToDB() {
		initDB();
		System.out.println("saving "+model.paths.size()+" paths to database");
		for (int i = 0; i < model.paths.size(); i++) {
			DataBaseSaver dbs = new DataBaseSaver(database);
			dbs.addListener(this);
			dbs.insert(model.paths.get(i));
		}
	}

	private void initDB() {
		try {

			database = new WikiSQLHelper(
					Settings.getString(Settings.KEY_DATABASE_LOCATION,
							"localhost"),
					Settings.getString(Settings.KEY_DATABASE_USERNAME, "root"),
					Settings.getString(Settings.KEY_DATABASE_PASSWORD, ""),
					Settings.getString(Settings.KEY_DATABASE_TABLENAME, "paths"));
			database.connect();

		} catch (Exception e) {
			view.log("Error connecting to database!");
			e.printStackTrace();
		}
	}

	@Override
	public void onDataBaseSavingFinished(Exception eventualError) {
		savingProgress++;
		double percentage = 100 * savingProgress
				/ Settings.getDouble(Settings.KEY_MAX_PATHS_VALUE, 100.0);

		if (eventualError == null) {
			view.log(percentage + "% done");
		} else if (eventualError.getMessage() != null) {
			view.log("SQL-Error: " + eventualError.getMessage());
		}

		if (percentage >= 100) {
			view.log("saving to database done!");
			finished();
		}
	}

	private void finished() {
		openUrl();
	}
	
	private void openUrl(){
		URI uri;
		try {
			
			String get = "location="+Settings.getString(Settings.KEY_DATABASE_LOCATION, WikiConfig.DEFAULT_DATABASE_LOCATION);
			get += "&name="+Settings.getString(Settings.KEY_DATABASE_NAME,WikiConfig.DEFAULT_DATABASE_NAME );
			get += "&table="+Settings.getString(Settings.KEY_DATABASE_TABLENAME,WikiConfig.DEFAULT_DATABASE_TABLENAME );
			get += "&user="+Settings.getString(Settings.KEY_DATABASE_USERNAME,WikiConfig.DEFAULT_USERNAME );
			get += "&password="+Settings.getString(Settings.KEY_DATABASE_PASSWORD,WikiConfig.DEFAULT_PASSWORD );
			
			uri = new URI(Settings.getString(Settings.KEY_RESULT_LOCATION, "http://localhost")+"?"+get);
			Desktop desktop = Desktop.getDesktop();
			desktop.browse(uri);
		} catch (URISyntaxException e) {
			view.log("Wrong syntax for result webpage!");
		} catch (IOException e) {
			view.log("Error opening webpage!");
		}
		System.exit(0);
	}
	

}
